
from django.shortcuts import render, redirect
from django.views import View
from QQLoginTool.QQtool import OAuthQQ
from django import http
# Django的配置模块,使用哪个配置文件启动,那么settings中就有哪个配置文件的数据
from django.conf import settings
from django.contrib.auth import login
from django_redis import get_redis_connection

from apps.oauth.models import OAuthQQUser
from meiduo_mall.utils.response_code import RETCODE
import logging,re
from apps.oauth.utils import generate_access_token_openid,check__access_token_openid
from apps.users.models import User

# Create your views here.

# 日志记录器
logger = logging.getLogger("django")



class QQAuthUserView(View):
    """用户扫码登陆的回调处理
    实现OAuth2.0认证取到openid
    """

    def get(self,request):
        """实现OAuth2.0认证获取到openid"""
        #　接收 Authorization Code
        code = request.GET.get("code")
        if not code:
            return http.HttpResponseForbidden("缺少code")

        # 初始化sdk对象:获取token的时候不需要在传入state了
        # client_id就是appid,
        oauth = OAuthQQ(client_id=settings.QQ_CLIENT_ID, client_secret=settings.QQ_CLIENT_SECRET,
                        redirect_uri=settings.QQ_REDIRECT_URI)
        # 由于是网络操作,会有延迟所以要try
        try:
            # 通过Authorization Code获取Access Token
            access_token = oauth.get_access_token(code)
            # 通过Access Token获取openid
            openid = oauth.get_open_id(access_token)
        except Exception as e:
            # logging.info(e)# 只在开发环境下才会输出
            logger.error(e)# 项目部署上线后最低的等级时error
            return http.HttpResponseServerError("OAuth2.0认证失败")

        # 使用openid查询该QQ用户是否绑定过美多商城用户
        try:
            oauth_model = OAuthQQUser.objects.get(openid=openid)
        except OAuthQQUser.DoesNotExist:
            # 如果openid没有绑定美多商城,创建用户并绑定openid

            # 哪个用户的openid还给那个用户自己保存,将发来的请求在还给美多商城即可
            access_token_openid = generate_access_token_openid(openid)
            context = {"access_token_openid":access_token_openid}
            # context = {"openid":openid} # 如此是明文,不行

            return render(request,"oauth_callback.html",context)
        else:
            # 如果openid已绑定,直接登陆美多商城系统
            # 实现状态保持
            # login(request, '认证后的用户：跟openid关联的用户即可(外键)')
            login(request,oauth_model.user)

            #  重定向state==next
            next = request.GET.get("state")
            response = redirect(next)

            # QQ登陆后的用户名写入到cookie
            response.set_cookie("username",oauth_model.user.username,max_age=3600*24*7)

            # 响应结果
            return response  # 此处打断点,进到dispatch,然后找到路由,路由在找到用户中心的类视图,找到页面


    def post(self,request):
        """openid绑定美多商城的用户"""

        #　接受参数
        mobile = request.POST.get("mobile")
        password = request.POST.get("password")
        sms_code_client = request.POST.get("sms_code")
        access_token_openid = request.POST.get("openid")
        # 校验参数
        # 判断参数是否齐全
        if not all([mobile, password, sms_code_client, access_token_openid]):
            return http.HttpResponseForbidden('缺少必传参数')
        # 判断手机号是否合法
        if not re.match(r'^1[3-9]\d{9}$', mobile):
            return http.HttpResponseForbidden('请输入正确的手机号码')
        # 判断密码是否合格
        if not re.match(r'^[0-9A-Za-z]{8,20}$', password):
            return http.HttpResponseForbidden('请输入8-20位的密码')
        # 判断短信验证码是否一致
        redis_conn = get_redis_connection('verify_code')
        sms_code_server = redis_conn.get('sms_%s' % mobile)
        if sms_code_server is None:
            return render(request, 'oauth_callback.html', {'sms_code_errmsg': '无效的短信验证码'})
        if sms_code_client != sms_code_server.decode():
            return render(request, 'oauth_callback.html', {'sms_code_errmsg': '输入短信验证码有误'})
        # 判断openid是否有效：错误提示放在sms_code_errmsg位置
        openid = check__access_token_openid(access_token_openid)
        if not openid:
            return render(request,"oauth_callback.html",{"openid_errmsg":"无效的openid"})

        # 判断手机号是否存在
        try:
            user = User.objects.get(mobile=mobile)
        except User.DoesNotExist:
            # 如果手机号对应的用户不存在: 使用手机号新建用户(手机号就是用户名)
            user = User.objects.create_user(username=mobile,
                                            password=password,
                                            mobile=mobile)
        else:
            # 如果手机号存在:校验密码
            if not user.check_password(password):
                return render(request, 'oauth_callback.html', {'account_errmsg': '账号或密码错误'})

        # 使用openid绑定以上得到的用户user
        try:
            OAuthQQUser.objects.create(openid=openid,user=user)
        except Exception as e:
            logger.error(e)
            return render(request, 'oauth_callback.html', {'qq_login_errmsg': 'QQ登录失败'})

        # 状态保持
        login(request,user)

        # 重定向state==next
        next = request.GET.get("state")
        response = redirect(next)

        # QQ登陆后用户名写入到cookie
        response.set_cookie("username",user.username,max_age=3600 * 24 * 7)

        # 响应结果
        return response



##########获取QQ登陆扫码页面####################
class QQAuthURLView(View):
    """获取QQ登陆扫码页面"""

    def get(self,request):
        """提供QQ登陆扫码页面的连接"""

        # 获取到next
        next = request.GET.get("next","/")

        # 初始化sdk对象
        # client_id就是appid,
        oauth = OAuthQQ(client_id=settings.QQ_CLIENT_ID,client_secret=settings.QQ_CLIENT_SECRET,
                        redirect_uri=settings.QQ_REDIRECT_URI,state=next)

        # SDK对象的调用方法
        login_url = oauth.get_qq_url()

        # 返回QQ登陆扫码页面连接
        return http.JsonResponse({"code":RETCODE.OK,"errmsg":"OK","login_url":login_url})
